/*
 *             Copyright (C) 2024 Steve Jrong
 *
 * 	   GitHub Homepage: https://www.github.com/SteveJrong
 *      Gitee Homepage: https://gitee.com/stevejrong1024
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stevejrong.waiter.user.model.aggregates;

import java.time.LocalDateTime;

import org.apache.commons.lang3.StringUtils;

import com.stevejrong.waiter.common.component.util.DateTimeUtil;
import com.stevejrong.waiter.common.component.util.SpringUtil;
import com.stevejrong.waiter.unique.id.component.generator.DBMainIdGenerator;
import com.stevejrong.waiter.user.model.entities.Sms;
import com.stevejrong.waiter.user.model.valueobjects.Gender;
import com.stevejrong.waiter.user.model.valueobjects.HasAdvanceAuth;
import com.stevejrong.waiter.user.model.valueobjects.HasDeleted;
import com.stevejrong.waiter.user.model.valueobjects.PartnerAliPayInfo;
import com.stevejrong.waiter.user.model.valueobjects.PartnerWxInfo;
import com.stevejrong.waiter.user.model.valueobjects.Status;
import com.stevejrong.waiter.user.model.valueobjects.ValidateResult;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import reactor.core.publisher.Mono;

/**
 * 聚合根（根实体） - 顾客
 * <p>
 * 此类，既是聚合根，协调管理其他实体和值对象；又是普通实体，自身也可拥有属性和方法。
 *
 * @author Steve Jrong
 * @since 1.0
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public final class Guest {
	
    private Long mainId; // 顾客ID，同时也是聚合根（根实体）ID
    private LocalDateTime createAt; // 创建时间，是普通属性
    private LocalDateTime updateAt; // 更新时间，是普通属性
    private PartnerWxInfo partnerWxInfo; // 顾客在第三方平台（微信）中的账户信息，是值对象
    private PartnerAliPayInfo partnerAliPayInfo; // 顾客在第三方平台（支付宝）中的账户信息，是值对象
    private String tel; // 顾客手机号码，是普通属性
    private Status status; // 顾客状态，为枚举类型，是值对象
    private HasDeleted hasDeleted; // 顾客是否删除，为枚举类型，是值对象

    private Sms sms; // 短信实体，是暂驻内存的实体

    private ValidateResult validateResult; // 顾客信息验证结果，是值对象

    /**
     * 创建顾客
     * <p>
     * 分析：
     * <ul>
     *     <li>创建顾客，是顾客自身的行为，故要在当前类（顾客聚合根/根实体）内实现</li>
     *     <li>创建顾客，属于当前类的职责，且是简单的原子性业务，故要在当前类（顾客聚合根/根实体）内实现</li>
     * </ul>
     * <p>
     *
     * @return 顾客聚合根
     */
    public Mono<Guest> create() {
    	return SpringUtil.getBean(DBMainIdGenerator.class).generate()
			.map(dbMainId -> {
				this.setMainId(Long.valueOf(dbMainId));
				this.setCreateAt(DateTimeUtil.getLocalDateTimeByNow());
		        this.setStatus(Status.ENABLE);
		        this.setHasDeleted(HasDeleted.NO_DELETED);
		        this.getPartnerWxInfo().setHasAdvancedAuth(HasAdvanceAuth.NO_ADVANCE_AUTH);
		        this.getPartnerWxInfo().setUserGender(Gender.UNKNOWN);
		        return this;
			});
    }

    /**
     * 更新顾客的手机号码
     * <p>
     * 是顾客自身的行为，在顾客聚合根内实现
     *
     * @return
     */
    public Guest updateTel(String tel) {
        this.setTel(tel);
        this.setUpdateAt(LocalDateTime.now());
        return this;
    }

    /**
     * 启用顾客
     *
     * @return
     */
    public Guest enable() {
        this.setUpdateAt(LocalDateTime.now());
        this.setStatus(Status.ENABLE);
        return this;
    }

    /**
     * 禁用顾客
     *
     * @return
     */
    public Guest disable() {
        this.setUpdateAt(LocalDateTime.now());
        this.setStatus(Status.DISABLE);
        return this;
    }

    /**
     * 删除顾客
     * <p>
     * 是顾客自身的行为，在顾客聚合根内实现
     *
     * @return
     */
    public Guest delete(String mainId) {
        this.setUpdateAt(LocalDateTime.now());
        this.setHasDeleted(HasDeleted.DELETED);
        return this;
    }

    /**
     * 反删除顾客
     * <p>
     * 是顾客自身的行为，在顾客聚合根内实现
     *
     * @return
     */
    public Guest unDelete(String mainId) {
        this.setUpdateAt(LocalDateTime.now());
        this.setHasDeleted(HasDeleted.NO_DELETED);
        return this;
    }

    /**
     * 校验顾客信息
     * <p>
     * 是顾客自身的行为，在顾客聚合根内实现
     *
     * @return
     */
    public Guest validate() {
        if (this.getStatus() == Status.DISABLE) {
            validateResult.setResult(false);
            validateResult.setMessage("账户已禁用");
        } else if (this.getHasDeleted() == HasDeleted.DELETED) {
            validateResult.setResult(false);
            validateResult.setMessage("账户已删除");
        }

        return this;
    }

    /**
     * 检查顾客是否绑定了手机号
     *
     * @return true - 已绑定；false - 未绑定
     */
    public boolean checkTelBound() {
        return StringUtils.isNotEmpty(this.getPartnerWxInfo().getUserOpenId());
    }
}